package com.dd;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.StackLayout;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;

public class ShadowLayout extends StackLayout implements ComponentContainer.DrawTask, ComponentContainer.EstimateSizeListener {
    private static HiLogLabel logLabel = new HiLogLabel(HiLog.LOG_APP, 0x001, "TAG");

    private static final int DEFAULT_RADIUS = 0;
    private static final float START = 0.1f;
    private static final float STOP = 0.7f;

    /**
     * 矩形
     */
    public static final int SHAPE_RECTANGLE = 0x0001;

    /**
     * 圆形
     */
    public static final int SHAPE_OVAL = 0x0010;

    private int mShadowShape = SHAPE_RECTANGLE;
    private int mShadowColor;
    private double mShadowRadius;
    private double mCornerRadius;
    private double mDx;
    private double mDy;

    private boolean mInvalidateShadowOnSizeChanged = true;
    private boolean mForceInvalidateShadow = false;
    private Paint shadowPaint = new Paint();
    private RectFloat mRectF = new RectFloat();

    public ShadowLayout(Context context) {
        super(context, null);
    }

    public ShadowLayout(Context context, AttrSet attrs) {
        this(context, attrs, null);
    }

    public ShadowLayout(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs);
        setEstimateSizeListener(this);
        addDrawTask(this);
    }

    @Override
    public int getMinWidth() {
        return super.getMinWidth();
    }

    @Override
    public int getMinHeight() {
        return super.getMinHeight();
    }

    @Override
    public boolean onEstimateSize(int w, int h) {
        if (w > 0 && h > 0) {
            if (getBackgroundElement() == null || mInvalidateShadowOnSizeChanged || mForceInvalidateShadow){
                mForceInvalidateShadow = false;
//            setBackgroundCompat(w, h);
            }
        }

        double rectLeft = 0;
        double rectTop = 0;
        double rectRight = this.getWidth();
        double rectBottom = this.getHeight();
        double paddingLeft = 0;
        double paddingTop = 0;
        double paddingRight = 0;
        double paddingBottom = 0;
        this.getWidth();

        if (String.valueOf(mDy) != null) {
            rectBottom = rectBottom - mDy;
        }
        if (String.valueOf(mDx) != null) {
            rectRight = (float) rectRight - mDx;
        }
        mRectF.left = (float) rectLeft;
        mRectF.top = (float) rectTop;
        mRectF.right = (float) rectRight;
        mRectF.bottom = (float) rectBottom;


        int xPadding = (int) (mShadowRadius + Math.abs(mDx));
        int yPadding = (int) (mShadowRadius + Math.abs(mDy));

//        if (mShadowShape == SHAPE_RECTANGLE) {
//            setPadding(0, 0, xPadding, yPadding);
//        } else if (mShadowShape == SHAPE_OVAL) {
//            this.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
//        }

        setPadding(0, 0, xPadding, yPadding);
        invalidate();
        return false;
    }

    public void setInvalidateShadowOnSizeChanged(boolean invalidateShadowOnSizeChanged) {
        mInvalidateShadowOnSizeChanged = invalidateShadowOnSizeChanged;
    }

    public void invalidateShadow() {
        mForceInvalidateShadow = true;
        postLayout();
        invalidate();
    }

    private void initView(Context context, AttrSet attrs) {
        initAttributes(context, attrs);

        initPaint();

    }

    private void initPaint() {
        shadowPaint.reset();
        shadowPaint.setDither(true);
        shadowPaint.setAntiAlias(true);
        shadowPaint.setColor(new Color(mShadowColor));
        shadowPaint.setStyle(Paint.Style.FILL_STYLE);
        shadowPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
//        shadowPaint.setStrokeJoin(Paint.Join.ROUND_JOIN);
        shadowPaint.setMaskFilter(new MaskFilter(50f, MaskFilter.Blur.OUTER));
    }

    @SuppressWarnings("deprecation")
//    private void setBackgroundCompat(int w, int h) {
//        PixelMap bitmap = createShadowBitmap(w, h, mCornerRadius, mShadowRadius, mDx, mDy, mShadowColor, Color.BLACK.getValue());
//        PixelMapElement element = new PixelMapElement(bitmap);
//
//        setBackground(element);
//    }

    private void initAttributes(Context context, AttrSet attrs) {
        mShadowShape = AttrUtil.getIntegerValue(attrs, "sl_shadowShape", SHAPE_RECTANGLE);

        mCornerRadius = AttrUtil.getDimension(attrs, "sl_cornerRadius", DEFAULT_RADIUS);
        mShadowRadius = AttrUtil.getDimension(attrs, "sl_shadowRadius", DEFAULT_RADIUS);
        mDx = AttrUtil.getDimension(attrs, "sl_dx", 0);
        mDy = AttrUtil.getDimension(attrs, "sl_dy", 0);
        mShadowColor = Color.getIntColor(AttrUtil.getStringValue(attrs, "sl_shadowColor", "#ff0000"));

    }

    private PixelMap createShadowBitmap(double shadowWidth, double shadowHeight, double cornerRadius, double shadowRadius,
                                        double dx, double dy, int shadowColor, int fillColor) {
        Canvas canvas = new Canvas();

        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size.width = (int) shadowWidth;
        initializationOptions.size.height = (int) shadowHeight;
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        PixelMap pixelMap = PixelMap.create(initializationOptions);
        canvas.drawPixelMapHolder(new PixelMapHolder(pixelMap), 0, 0, null);

        RectFloat shadowRect = new RectFloat(
                (float) shadowRadius,
                (float) shadowRadius,
                (float) (shadowWidth - shadowRadius),
                (float) (shadowHeight - shadowRadius));

        if (dy > 0) {
            shadowRect.top += dy;
            shadowRect.bottom -= dy;
        } else if (dy < 0) {
            shadowRect.top += Math.abs(dy);
            shadowRect.bottom -= Math.abs(dy);
        }

        if (dx > 0) {
            shadowRect.left += dx;
            shadowRect.right -= dx;
        } else if (dx < 0) {
            shadowRect.left += Math.abs(dx);
            shadowRect.right -= Math.abs(dx);
        }

        Paint shadowPaint = new Paint();
        shadowPaint.setAntiAlias(true);
        shadowPaint.setColor(new Color(fillColor));
        shadowPaint.setStyle(Paint.Style.FILL_STYLE);

        Point[] newPoints = getBoundPoint(shadowRect);
        float[] newStops = new float[]{START, STOP};
        Color[] colors = new Color[]{new Color(mShadowColor)};

        /**
         * 添加着色器 坐标点，渐变值组，颜色值组，模式
         */
        LinearShader shader = new LinearShader(newPoints, newStops, colors, Shader.TileMode.CLAMP_TILEMODE);
        shadowPaint.setShader(shader, Paint.ShaderType.LINEAR_SHADER);
        /**
         * 绘制宽度
         */
        shadowPaint.setStrokeWidth((float) mShadowRadius);

        canvas.drawRoundRect(shadowRect, (float) cornerRadius, (float) cornerRadius, shadowPaint);

        return pixelMap;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {

        initPaint();
        RectFloat shadowRect = new RectFloat(
                0,
                0,
                (float)(component.getWidth() - mShadowRadius),
                (float)(component.getHeight() - mShadowRadius));

        if (mDy > 0) {
            shadowRect.top = (float) ((double)shadowRect.top + 0);
            shadowRect.bottom -= mDy;
        } else if (mDy < 0) {
            shadowRect.top += Math.abs(mDy);
            shadowRect.bottom -= Math.abs(mDy);
        }

        if (mDx > 0) {
            shadowRect.left = (float) ((double)shadowRect.left + 0);
            shadowRect.right -= mDx;
        } else if (mDx < 0) {
            shadowRect.left += Math.abs(mDx);
            shadowRect.right -= Math.abs(mDx);
        }

        Point[] newPoints = getBoundPoint(shadowRect);
        float[] newStops = new float[]{START, STOP};
        Color[] colors = new Color[]{new Color(mShadowColor), Color.TRANSPARENT};

        /**
         * 添加着色器 坐标点，渐变值组，颜色值组，模式
         */
        LinearShader shader = new LinearShader(newPoints, newStops, colors, Shader.TileMode.CLAMP_TILEMODE);
        shadowPaint.setShader(shader, Paint.ShaderType.LINEAR_SHADER);

//        shadowPaint.setCornerPathEffectRadius(mCornerRadius);

        /**
         * 绘制宽度
         */
        shadowPaint.setStrokeWidth((float) mShadowRadius);
        HiLog.error(logLabel, "------" + mShadowShape);

//        if (mShadowShape == SHAPE_RECTANGLE) {
//            HiLog.error(logLabel,"------"+mShadowShape);
//
//            canvas.drawRect(shadowRect, shadowPaint);
//        } else if (mShadowShape == SHAPE_OVAL) {
//            HiLog.error(logLabel,"------"+mShadowShape);
//
//            shadowPaint.setCornerPathEffectRadius(mShadowRadius);
//
//            Point[] newPoints1 = getBoundPoint(mRectF);
//            float[] newStops1 = new float[]{START, STOP};
//            Color[] colors1 = new Color[]{new Color(mShadowColor), Color.TRANSPARENT};
//
//            /**
//             * 添加着色器 坐标点，渐变值组，颜色值组，模式
//             */
//            LinearShader shader1 = new LinearShader(newPoints1, newStops1, colors1, Shader.TileMode.CLAMP_TILEMODE);
//            shadowPaint.setShader(shader1, Paint.ShaderType.LINEAR_SHADER);
//
//            canvas.drawCircle(shadowRect.getHorizontalCenter(), shadowRect.getVerticalCenter(),
//                    Math.min(shadowRect.getWidth(), shadowRect.getHeight()) / 2, shadowPaint);
////            canvas.drawCircle(new Circle(shadowRect.getHorizontalCenter(), shadowRect.getVerticalCenter(),Math.min(shadowRect.getWidth(), shadowRect.getHeight()) / 2),shadowPaint);
//        }

        canvas.drawRoundRect(shadowRect, (float) mCornerRadius, (float)mCornerRadius, shadowPaint);
    }

    /**
     * 获取绑定点
     *
     * @param rectFloat
     * @return Point[]
     */
    private Point[] getBoundPoint(RectFloat rectFloat) {
        Point point1 = new Point(rectFloat.left, rectFloat.top);
        Point point2 = new Point(rectFloat.left, rectFloat.bottom);
        Point point3 = new Point(rectFloat.right, rectFloat.bottom);
        Point point4 = new Point(rectFloat.right, rectFloat.top);

        return new Point[]{point1, point2, point3, point4};
    }
}
